﻿/*
  Copyright © Alexander G. Bykin, Russia 2009-2010
  This source is subject to the Microsoft Public License (Ms-PL).
  Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
  All rights reserved.
*/

namespace GoogleVisualizationAPI
{
    using System.Collections.Generic;
    using System.Web.UI;
    using System.Data.Linq;
    using System;

    public partial class GoogleVisualization : System.Web.UI.UserControl
    {
        #region Private Properties

        #region Private Property GVAPIVersion

        /// <summary>
        /// 
        /// </summary>
        private readonly int GVAPIVersion = 1;

        #endregion

        #region Private Property _Visualization

        /// <summary>
        /// 
        /// </summary>
        private IList<Visualization> _Visualization { get; set; }

        #endregion

        #endregion

        #region Public Properties

        #region Public Property Visualization

        /// <summary>
        /// 
        /// </summary>
        public IList<Visualization> Visualization
        {
            get
            {
                if (this._Visualization == null)
                {
                    this._Visualization = new List<Visualization>();
                }
                return this._Visualization;
            }
            set
            {
                this._Visualization = value;
            }
        }

        #endregion

        #endregion

        #region Private Methods

        #region Private Method GetJSMethodNameByPackageType

        /// <summary>
        /// Gets JavaScript method name by VisualizationPackage type.
        /// </summary>
        /// <param name="visualPackage">The VisualizationPackage</param>
        /// <returns>JavaScript method name by VisualizationPackage type.</returns>
        private string GetJSMethodNameByPackageType(VisualizationPackage visualPackage)
        {
            string result = string.Empty;

            if (!Enum.IsDefined(typeof(VisualizationPackage), visualPackage))
            {
                return result;
            }

            switch (visualPackage)
            {
                case VisualizationPackage.ColumnChart:
                case VisualizationPackage.ImageSparkLine:
                case VisualizationPackage.ImageAreaChart:
                case VisualizationPackage.ImageLineChart:
                case VisualizationPackage.LineChart:
                case VisualizationPackage.PieChart:
                case VisualizationPackage.Table:
                    result = "setCell";
                    break;
                case VisualizationPackage.AnnotatedTimeLine:
                case VisualizationPackage.AreaChart:
                case VisualizationPackage.BarChart:
                case VisualizationPackage.Gauge:
                case VisualizationPackage.GeoMap:
                case VisualizationPackage.ImageChart:
                case VisualizationPackage.ImagePieChart:
                case VisualizationPackage.IntensityMap:
                case VisualizationPackage.MotionChart:
                case VisualizationPackage.OrgChart:
                case VisualizationPackage.ScatterChart:
                    result = "setValue";
                    break;
            }

            return result;
        }

        #endregion

        #region Private Method GetFormattedCellValueByDataType

        /// <summary>
        /// Gets formatted string value by DataType.
        /// </summary>
        /// <param name="dataType">The DataType.</param>
        /// <param name="dataValue">The value that need to convert.</param>
        /// <returns>Formatted string value by DataType</returns>
        private string GetFormattedCellValueByDataType(DataType dataType, string dataValue)
        {
            string result = string.Empty;

            if (!Enum.IsDefined(typeof(DataType), dataType) || string.IsNullOrEmpty(dataValue))
            {
                return result;
            }

            switch (dataType)
            {
                case DataType.Number:
                    result = dataValue;
                    break;
                case DataType.String:
                    result = string.Format("'{0}'", dataValue);
                    break;
                case DataType.Date:
                    DateTime dateTime = Convert.ToDateTime(dataValue, System.Globalization.CultureInfo.CurrentCulture);
                    result = string.Format("new Date({0}, {1}, {2})", dateTime.Year, dateTime.Month, dateTime.Day);
                    break;
            }

            return result;
        }

        #endregion

        #endregion

        #region Protected Methods

        #region Protected Method Render

        protected override void Render(HtmlTextWriter writer)
        {
            if (this.Visualization == null)
                return;

            if (this.Visualization.Count == 0)
                return;

            writer.Write("<script type=\"text/javascript\" src=\"http://www.google.com/jsapi\"></script>\n");

            writer.Write("<script type=\"text/javascript\">\n");

            foreach (var visual in this.Visualization)
            {
                writer.Write(string.Format("google.load('{0}', '{1}', {{'packages': ['{2}']}});\n", visual.ModuleName, this.GVAPIVersion, visual.Package.ToString().ToLower()));
            }
            writer.Write("</script>\n");
            writer.Write("<script type=\"text/javascript\">\n");
            writer.Write("function drawVisualization() {\n");

            int counter = 0;

            foreach (var visual in this.Visualization)
            {
                if (visual.DataTable.ListOfDataCell == null)
                    continue;

                if (visual.DataTable.ListOfDataCell.Count == 0)
                    continue;

                if (visual.DataTable.ListOfDataColumn == null)
                    continue;

                if (visual.DataTable.ListOfDataColumn.Count == 0)
                    continue;

                if (string.IsNullOrEmpty(visual.DisplayOptions))
                {
                    visual.DisplayOptions = "null";
                }

                string JSDataSource = string.Format("data{0}", counter);

                string JSMethodName = this.GetJSMethodNameByPackageType(visual.Package);

                writer.Write(string.Format("var {0} = new google.visualization.DataTable();\n", JSDataSource));

                foreach (var dataColumn in visual.DataTable.ListOfDataColumn)
                {
                    writer.Write(string.Format("{0}.addColumn('{1}', '{2}');\n", JSDataSource, dataColumn.DataType.ToString().ToLower(), dataColumn.Name));
                }

                writer.Write(string.Format("{0}.addRows({1});\n", JSDataSource, visual.DataTable.ListOfDataCell.Count));

                int rowIdx = 0;
                int columnIdx = 0;
                foreach (DataCell dataCell in visual.DataTable.ListOfDataCell)
                {
                    rowIdx = 0;

                    DataType columnDataType = visual.DataTable.ListOfDataColumn[0].DataType;
                    string columnDataResult = this.GetFormattedCellValueByDataType(columnDataType, dataCell.Caption);

                    writer.Write(string.Format("{0}.{1}({2}, {3}, {4});\n", JSDataSource, JSMethodName, columnIdx, rowIdx, columnDataResult));

                    foreach (var dataCellValue in dataCell.Value)
                    {
                        rowIdx++;

                        if (rowIdx > visual.DataTable.ListOfDataColumn.Count - 1)
                        {
                            break;
                        }

                        columnDataType = visual.DataTable.ListOfDataColumn[rowIdx].DataType;

                        if (string.IsNullOrEmpty(dataCellValue))
                        {
                            continue;
                        }

                        string dataCellResult = this.GetFormattedCellValueByDataType(columnDataType, dataCellValue);
                        writer.Write(string.Format("{0}.{1}({2}, {3}, {4});\n", JSDataSource, JSMethodName, columnIdx, rowIdx, dataCellResult));
                    }
                    columnIdx++;
                }

                #region DisplayOptions Patch from mschaunaman

                writer.Write(string.Format("new google.visualization.{0}(document.getElementById('{1}')).draw({2}, {3});\n", visual.Package, visual.DestObjectName, JSDataSource, visual.DisplayOptions));

                #endregion

                counter++;
            }
            writer.Write("}\n");
            writer.Write("google.setOnLoadCallback(drawVisualization);\n");
            writer.Write("</script>");
        }

        #endregion

        #endregion
    }
}